// 整个commit阶段将要处理的节点
let nextEffect = null
export function commitBeforeMutationEffects(root, firstChild) {
	/* 
        root 为 fiberRoot
        firstChild 为render阶段调和完毕的fiber节点 
    */
	nextEffect = firstChild
	/* 开始进入 before mutation 流程 */
	commitBeforeMutationEffects_begin()
}
/* 
    解释了 commit阶段执行的生命周期或者effect钩子先子后父
    commit 阶段生命周期是可以改变真实 dom 元素，所以如果在子组件生命周期内改变dom状态，
    并且想要在父组件的生命周期中同步状态，就需要确保父组件的生命周期执行时机要晚于子组件

    向下递归
*/
function commitBeforeMutationEffects_begin() {
	while (nextEffect !== null) {
		let fiber = nextEffect
		let child = fiber.child
		if (
			(fiber.subtreeFlags & BeforeMutationMask) !== NoFlags &&
			child !== null
		) {
			/* 
                这里如果子代fiber树有 before mutation 的标志，那么把 fiber 赋值给
                子代 nextEffect 
            */
			nextEffect = child
		} else {
			/* 找到最底层有 before mutation 的标志的 fiber ，执行 complete */
			commitBeforeMutationEffects_complete()
		}
	}
}
/* 向上递归 */
function commitBeforeMutationEffects_complete() {
	while (nextEffect !== null) {
		let fiber = nextEffect
		try {
			/* 真正的处理 before mutation 需要做的事情 */
			commitBeforeMutationEffectsOnFiber(fiber)
		} finally {
			/* 优先处理兄弟节点上的 before mutation */
			let sibling = fiber.sibling
			if (sibling !== null) {
				nextEffect = sibling
				return
			}
			/* 如果没有兄弟节点，那么返回父级节点，继续进行流程 */
			nextEffect = fiber.return
		}
	}
}
/* 
    处理 Snapshot ，获取 DOM 更新前的快照信息 包括类组件执行生命周期 getSnapshotBeforeUpdate 
    beforeMutation 事情执行完毕
*/
function commitBeforeMutationEffectsOnFiber(fiber) {
	if ((flags & Snapshot) !== NoFlags) {
		/* 如果有 Snapshot 标志 */
		switch (finishedWork.tag) {
			case ClassComponent:
				let snapshot = instance.getSnapshotBeforeUpdate(
					finishedWork.elementType === finishedWork.type
						? prevProps
						: resolveDefaultProps(finishedWork.type, prevProps),
					prevState
				)
				instance.__reactInternalSnapshotBeforeUpdate = snapshot
		}
	}
}
export function commitMutationEffects(root, firstChild, lanes) {
	nextEffect = firstChild
	commitMutationEffects_begin(root, lanes)
}
function commitMutationEffects_begin(root, lanes) {
	while (nextEffect !== null) {
		let fiber = nextEffect
		let child = fiber.child
		let deletions = fiber.deletions
		if (deletions !== null) {
			for (let i = 0; i < deletions.length; i++) {
				let childToDelete = deletions[i]
				commitDeletion(root, childToDelete, fiber)
			}
		}
		if ((fiber.subtreeFlags & MutationMask) !== NoFlags && child !== null) {
			nextEffect = child
		} else {
			/* 找到最底层有 mutation 的标志的 fiber ，执行 complete */
			commitMutationEffects_complete()
		}
	}
}
/* 删除节点 */
function commitDeletion(root, node, fiber) {
	// dom 元素
	if (node.tag === HostComponent || node.tag === HostText) {
		unmountHostComponents(node, fiber)
	} else {
		commitUnmount()
	}
}
/* 调用真实 dom 操作方法，删除 dom 元素 */
function unmountHostComponents(node, currentParent) {
	currentParent.removeChild(node.stateNode)
}
function commitUnmount(current) {
	switch (current.tag) {
		case FunctionComponent:
		case ForwardRef:
		case MemoComponent:
		case SimpleMemoComponent:
			{
				/* 函数组件执行所有的 effect 销毁函数的 destroy*/
				if (destroy !== undefined) {
					if ((tag & Insertion) !== NoFlags$1) {
						/* 执行 useInsertionEffect 的 destroy */
						safelyCallDestroy(
							current,
							nearesMountedAncestor,
							destroy
						)
					} else if ((tag & Layout) !== NoFlags$1) {
						/* 执行 useLayoutEffect 的 destroy */
						safelyCallDestroy(
							current,
							nearesMountedAncestor,
							destroy
						)
					}
				}
			}
			break
		case ClassComponent:
			{
				/* 清空 ref */
				safelyCallRef(current, nearesMountedAncestor)
				let instance = current.stateNode
				if (typeof instance.componentWillUnmount === 'function') {
					/* 调用类组件生命周期 componentWillUnmount */
					safelyCallComponentWillUnmount(
						current,
						nearesMountedAncestor,
						instance
					)
				}
			}
			break
	}
}
/* 向上递归 */
function commitMutationEffects_complete() {
	while (nextEffect !== null) {
		let fiber = nextEffect
		try {
			/* 真正的处理 mutation 需要做的事情 */
			commitMutationEffectsOnFiber(fiber)
		} finally {
			/* 优先处理兄弟节点上的  mutation */
			let sibling = fiber.sibling
			if (sibling !== null) {
				nextEffect = sibling
				return
			}
			/* 如果没有兄弟节点，那么返回父级节点，继续进行流程 */
			nextEffect = fiber.return
		}
	}
}
function commitMutationEffectsOnFiber() {
	if (flags & ContentReset) {
		commitResetTextContent(finishedWork)
	}
	/* 如果是 ref 更新，那么重置 alternate 属性上的ref  */
	if (flags & Ref) {
		let current = finishedWork.alternnate
		if (current !== null) {
			commitDetachRef(current)
		}
	}
	if (flags & Visibility) {
		/* v18 新特性 */
	}
	let primaryFlags = flags & (Placement | Update)
	switch (primaryFlags) {
		/* 插入新节点 */
		case Placement: {
			commitPlacement(finishedWork)
			finishedWork.flags &= ~Placement
			break
		}
		/* 更新 */
		case Update: {
			let _current5 = finishedWork.alternnate
			commitWork(_current5, finishedWork)
			break
		}
	}
}
/**
 * 置空文本的内容
 */
function commitResetTextContent() {
	/* node 为 stateNode 属性，为 fiber 元素的真实节点 */
	let firstChild = node.firstChild
	if (
		firstChild &&
		firstChild === node.lastChild &&
		firstChild.nodeType === TEXT_NODE
	) {
		firstChild.nodeValue = ''
		return
	}
}
function commitDetachRef() {}
function commitPlacement(finishedWork) {
	/* 获取父级 fiber */
	let parentFiber = getHostParentFiber(finishedWork)
	switch (parentFiber.tag) {
		/* 元素节点 div */
		case HostComponent:
			/* 获取下一个兄弟节点  */
			let before = getHostSibling(finishedWork)
			/* 插入节点 */
			insertOrAppendPlacementNode(finishedWork, before, parent)
			break
	}
}

function insertOrAppendPlacementNode(finishedWork, before, parent) {
	/* 如果有兄弟节点，往兄弟节点之前加 */
	if (before) {
		insetBefore(parent, stateNode, before)
	} else {
		/* 插入最后一个节点 */
		appendChild(parent, stateNode)
	}
}
function commitWork(current, finishedWork) {
	switch (finishedWork.tag) {
		case FunctionComponent:
		case ForwardRef:
		case MemoComponent:
		case SimpleMemoComponent:
			/* 先执行上一次 useInsertionEffect 的 destory */
			commitHookEffectListUnmount(
				Insertion | HasEffect,
				finishedWork,
				finishedWork.return
			)
			/* 执行 useInsertionEffect 的 create */
			commitHookEffectListMount(Insertion | HasEffect, finishedWork)
			break
		case HostComponent:
			/* 元素节点会执行 commitUpdate */
			if (updatePayload !== null) {
				commitUpdate(instance, updatePayload, type, oldProps, newProps)
			}
			break
		case HostText:
			/* 文本节点更新 */
			commitTextUpdate(textInstance, oldText, newText)
			break
	}
}
function commitTextUpdate() {
	if (propKey === STYLE) {
		/* 更新 style 信息 */
		setValueForStyle(domElement, propValue)
	} else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
		/* 更新 innerHtml */
		setInnerHTML(domElement, propValue)
	} else if (propKey === CHILDREN) {
		/* 更新 nodeValue 属性 */
		setTextContent(domElement, propValue)
	} else {
		/* 更新元素的 props */
		setValueForProperty(domElement, propValue)
	}
}

export function commitLayoutEffects(root, firstChild, lanes) {
	nextEffect = firstChild
	commitLayoutEffects_begin(root, lanes)
}
function commitLayoutEffects_begin() {
	while (nextEffect !== null) {
		if (fiber.tag === OffscreenComponent && isModernRoot) {
			/* 对于 OffscreenComponent 逻辑 */
		}
	}
}
function commitLayoutEffectsOnFiber(
	finishedRoot,
	current,
	finishedWork,
	committedLanes
) {
	if ((finishedWork.flags & LayoutMask) !== NoFlags) {
		switch (finishedWork.tag) {
			/* 对于函数组件  执行 useLayoutEffect */
			case FunctionComponent:
			case ForwardRef:
			case SimpleMemoComponent:
				commitHookEffectListMount(Layout | HasEffect, finishedWork)
				break
			/* 对于类组件，初始化会执行 componentDidMount,更新会执行 componentDidUpdate */
			case ClassComponent:
				let intance = finishedWork.stateNode
				if (finishedWork.flags & Update) {
					if (current !== null) {
						/* 执行 componentDidMount */
						intance.componentDidMount()
					} else {
						intance.componentDidUpdate(
							prevProps,
							prevState,
							intance.__reactInternalSnapshotBeforeUpdate
						)
					}
				}
				let updateQueue = finishedWork.updateQueue
				/* 如果有 setState 的callback ，执行回调函数 */
				if (updateQueue !== null) {
					commitUpdate(finishedWork, updateQueue, intance)
				}
				break
		}
	}

	if (finishedWork.flags & Ref) {
		/* 更新 ref 属性 */
		commitAttachRef(finishedWork)
	}
}
function commitPassiveMountOnFiber(finishedRoot, finishedWork) {
	switch (finishedWork.tag) {
		case FunctionComponent:
		case ForwardRef:
		case SimpleMemoComponent:
			/* 执行所有的 useEffect 的钩子函数 */
			commitHookEffectListMount(Passive$1 | HasEffect, finishedWork)
			break
	}
}
function commitHookEffectListMount(flags, finishedWork) {
	let updateQueue = finishedWork.updateQueue
	let lastEffect = updateQueue !== null ? updateQueue.lastEffect : null
	if (lastEffect !== null) {
		let firstEffect = lastEffect.next
		let effect = firstEffect
		if ((effect.tag & flags) === flags) {
			let create = effect.create
			/* 执行 effect hooks 钩子函数，得到 destroy 函数 */
			effect.destroy = create()
		}
	}
}
